/**
 * @file drv_ad_det.c
 * @brief AD_DET 模拟串口收发驱动(纯中断接收)
 * @date 2025-11-03
 *
 * @note 硬件配置说明：
 *       FEATURE_DEBUG_DISABLE_AD_DET_INPUT_PA13 = 1 (调试模式):
 *         - RX: PA13 (AD_DET2), TX: PA14 (AD_DET1)
 *         - 用于调试板，PB8被BOOT占用
 *       FEATURE_DEBUG_DISABLE_AD_DET_INPUT_PA13 = 0 (正常模式):
 *         - RX: PB8 (AD_DET), TX: PA14 (AD_DET1)
 *         - 用于客户板，正常硬件配置
 */

#include "user_config.h"
#include "main.h"
#include "drv_ad_det.h"
#include "sys_manager.h"
#include "sys.h"

/* 私有函数 */
static void ad_det_gpio_init(void);

#if (FEATURE_DEBUG_BYPASS_BOARD_MANAGER == 0)
static uint8_t recv_data_in_isr(void);
#endif

/**
 * @brief 初始化 AD_DET 驱动
 * @note 启动时延时5秒，给调试器足够时间连接
 */
int drv_ad_det_init(void)
{
    ad_det_gpio_init();
    return 0;
}

/**
 * @brief 发送字符（通过PA14/PB8）
 */
int drv_ad_det_send_char(uint8_t data)
{
    /* 发送起始位 */
    HAL_GPIO_WritePin(AD_DET_TX_PORT, AD_DET_TX_PIN, GPIO_PIN_RESET);
    delay_us(AD_DET_BIT_TIME_US);

    /* 发送 8 个数据位（LSB 先发送）*/
    for (uint8_t i = 0; i < 8; i++)
    {
        uint8_t bit = data & 0x01;
        HAL_GPIO_WritePin(AD_DET_TX_PORT, AD_DET_TX_PIN, (GPIO_PinState)bit);
        delay_us(AD_DET_BIT_TIME_US);
        data >>= 1;
    }

    /* 发送停止位 */
    HAL_GPIO_WritePin(AD_DET_TX_PORT, AD_DET_TX_PIN, GPIO_PIN_SET);
    delay_us(AD_DET_BIT_TIME_US);

    return 0;
}

/* 私有函数实现 */

/**
 * @brief 初始化 GPIO
 */
static void ad_det_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    /* 注意: STM32F0 不需要显式禁用 SWD
     * 当 PA13/PA14 被配置为普通 GPIO 时，SWD 功能会自动禁用
     * 所以下面的 GPIO 配置会自动释放调试引脚
     */

    /* PA14 输出 (发送引脚) */
    GPIO_InitStruct.Pin = AD_DET_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(AD_DET_TX_PORT, &GPIO_InitStruct);
    HAL_GPIO_WritePin(AD_DET_TX_PORT, AD_DET_TX_PIN, GPIO_PIN_SET);

    /* 接收引脚 + 下降沿中断 (根据宏选择 PA13 或 PB8) */
    GPIO_InitStruct.Pin = AD_DET_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(AD_DET_RX_PORT, &GPIO_InitStruct);

#if (FEATURE_DEBUG_DISABLE_AD_DET_INPUT_PA13 == 1)
    /* 调试模式: PA13 使用 EXTI4_15 */
    HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
#else
    /* 正常模式: PB8 使用 EXTI4_15 */
    HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
#endif
}

#if (FEATURE_DEBUG_BYPASS_BOARD_MANAGER == 0)
/**
 * @brief 在中断中接收单个字符（参考代码优化版）
 */
static uint8_t recv_data_in_isr(void)
{
    uint8_t ch = 0;

    /* 等待到起始位的中心位置（1.5倍位时间）*/
    delay_us(AD_DET_BIT_TIME_US + AD_DET_BIT_TIME_US / 2);

    /* 接收 8 个数据位（LSB 先接收）*/
    for (uint8_t i = 0; i < 8; i++)
    {
        uint8_t bit = HAL_GPIO_ReadPin(AD_DET_RX_PORT, AD_DET_RX_PIN);
        ch >>= 1;
        if (bit)
        {
            ch |= 0x80;
        }
        delay_us(AD_DET_BIT_TIME_US);
    }

    /* 等待停止位 */
    delay_us(AD_DET_BIT_TIME_US / 5);

    return ch;
}

/**
 * @brief EXTI中断回调（接收数据）
 * @note 警告：中断执行时间较长，可能影响其他中断响应
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin != AD_DET_RX_PIN)
    {
        return;
    }

    /* 在中断中完成接收 */
    uint8_t ch = recv_data_in_isr();

    /* 在BOOT模式下，立即调用系统管理器处理板号分配 */
    if (sys_manager_get_state() == SYS_STATE_BOOT)
    {
        sys_manager_gpio_isr_callback(ch);
    }
}
#endif /* FEATURE_DEBUG_BYPASS_BOARD_MANAGER */

/******************************** 文件结束 *********************************/
